#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>
#include <sys/wait.h>

#define FILENAME "/tmp/out"
#define N		 20 
#define BUFFSIZE 32
int semid;

static void V (void);
static void P (void);
int main (void)
{
	FILE *fp = NULL;
	int i = 0;
	//进程创建信号量, 创建子进程并给子进程收尸, 初始化文件 
	fp = fopen (FILENAME, "w");
	if (NULL == fp) {
		perror ("fopen()");
		return -1;
	}
	fputs ("0", fp);
	fclose (fp);
	//创建信号量集 创建的信号量集中只有一个信号量 
	//0表示信号量集中的第一个信号量 
	semid = semget (IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0600);
	if (-1 == semid) {
		perror ("semget()");
		return -1;
	}
	//将信号量集中的 信号量置1 
	semctl (semid, 0, SETVAL, 1);
	
	//创建子进程
	for (i = 0; i < N; i++) {
		pid_t pid = fork ();
		if (-1 == pid) {
			perror ("fork()");
			goto ERROR;
		}
		if (0 == pid) {
			char buf[BUFFSIZE] = {0};
			P();
			//io 
			fp = fopen (FILENAME, "r+");
			if (NULL == fp) {
				perror ("fopen()");
				return -1;
			}
			fgets (buf, BUFFSIZE, fp);
			//定位文件流 
			rewind (fp);
			fprintf (fp, "%d", atoi(buf)+1);
			fclose (fp);
			V();
			exit (0);
		} 
	}
	for (i = 0; i < N; i++) {
		wait (NULL);
	}
	semctl (semid, 0, IPC_RMID, NULL);
	return 0;
ERROR:
	//销毁信号量
	semctl (semid, 0, IPC_RMID, NULL);
	exit (0);
}

static void P (void)
{
	struct sembuf sem;
	sem.sem_num = 0;
	sem.sem_op = -1;
	sem.sem_flg = 0;
	if (-1 == semop (semid, &sem, 1)) {
		perror ("semop");
	}
	return ;
}

static void V (void)
{
	struct sembuf sem;
	sem.sem_num = 0;
	sem.sem_op = 1;
	sem.sem_flg = 0;
	if (-1 == semop (semid, &sem, 1)) {
		perror ("semop");
	}
	return ;
}
